#region Copyright (c) 2003, newtelligence AG. All rights reserved.
/*
// Copyright (c) 2003, newtelligence AG. (http://www.newtelligence.com)
// Original BlogX Source Code: Copyright (c) 2003, Chris Anderson (http://simplegeek.com)
// All rights reserved.
//  
// Redistribution and use in source and binary forms, with or without modification, are permitted 
// provided that the following conditions are met: 
//  
// (1) Redistributions of source code must retain the above copyright notice, this list of 
// conditions and the following disclaimer. 
// (2) Redistributions in binary form must reproduce the above copyright notice, this list of 
// conditions and the following disclaimer in the documentation and/or other materials 
// provided with the distribution. 
// (3) Neither the name of the newtelligence AG nor the names of its contributors may be used 
// to endorse or promote products derived from this software without specific prior 
// written permission.
//      
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -------------------------------------------------------------------------
//
// Original BlogX source code (c) 2003 by Chris Anderson (http://simplegeek.com)
// 
// newtelligence is a registered trademark of newtelligence Aktiengesellschaft.
// 
// For portions of this software, the some additional copyright notices may apply 
// which can either be found in the license.txt file included in the source distribution
// or following this notice. 
//
*/
#endregion

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using newtelligence.DasBlog.Runtime;
using System.Xml;
using System.Xml.Serialization;
using newtelligence.DasBlog.Web.Core;
using newtelligence.DasBlog.Web.Services.Atom03;
using newtelligence.DasBlog.Util.Html;

namespace newtelligence.DasBlog.Web.Services
{
    /// <summary>
    /// Summary description for SyndicationServiceExperimental.
    /// </summary>
    [WebService(Namespace="urn:schemas-newtelligence-com:dasblog:syndication-services:experimental")]
    public class SyndicationServiceExperimentalImplementation : SyndicationServiceBase 
    {
        protected bool inASMX = false;

        public SyndicationServiceExperimentalImplementation()
        {
            //CODEGEN: This call is required by the ASP.NET Web Services Designer
            InitializeComponent();
        }

        public SyndicationServiceExperimentalImplementation(SiteConfig siteConfig, IBlogDataService dataService, ILoggingDataService loggingService):
            base( siteConfig, dataService, loggingService )
        {
            //CODEGEN: This call is required by the ASP.NET Web Services Designer
            InitializeComponent();
        }


        #region Component Designer generated code
		
        //Required by the Web Services Designer 
        private IContainer components = null;
				
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if(disposing && components != null)
            {
                components.Dispose();
            }
            base.Dispose(disposing);		
        }
		
        #endregion

        [WebMethod]
        [SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Wrapped,Use=SoapBindingUse.Literal)]
        public AtomRoot GetAtom()
        {
            int maxDays = siteConfig.RssDayCount;
			int maxEntries = siteConfig.RssMainEntryCount;
			return GetAtomWithCounts(maxDays, maxEntries);
        }

        [WebMethod]
        [SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Wrapped,Use=SoapBindingUse.Literal)]
        public AtomRoot GetAtomCategory(string categoryName)
        {
            return GetAtomCore(categoryName, 0, 0);
        }

        [WebMethod]
        [SoapDocumentMethod(
             ParameterStyle=SoapParameterStyle.Wrapped,
             Use=SoapBindingUse.Literal)]
        public AtomRoot GetAtomWithCounts(int maxDayCount, int maxEntryCount)
        {
            return GetAtomCore(null, maxDayCount, maxEntryCount);
        }

        private AtomRoot GetAtomCore(string category, int maxDayCount, int maxEntryCount)
        {
			EntryCollection entries = null;
			//We only build the entries if blogcore doesn't exist and we'll need them later...
			if (dataService.GetLastEntryUpdate() == DateTime.MinValue)
			{
				entries = BuildEntries(category, maxDayCount, maxEntryCount);			
			}

			//Try to get out as soon as possible with as little CPU as possible
			if ( inASMX )
			{
				if (GetStatusNotModified(GetLatestModifedEntryDateTime(entries)))
					return null;
			}

			if ( inASMX )
			{
				string referrer = Context.Request.UrlReferrer!=null?Context.Request.UrlReferrer.AbsoluteUri:"";
				if (ReferralBlackList.IsBlockedReferrer(referrer))
				{
					if (siteConfig.EnableReferralUrlBlackList404s)
					{
						return null;
					}
				}
				else
				{
					loggingService.AddReferral(
						new LogDataItem(
						Context.Request.RawUrl,
						referrer,
						Context.Request.UserAgent));
				}
			}

			
			//not-modified didn't work, do we have this in cache?
			string CacheKey = "Atom:" + category + ":" + maxDayCount.ToString() + ":" + maxEntryCount.ToString();
			AtomRoot atomFeed = HttpContext.Current.Cache[CacheKey] as AtomRoot;
			if (atomFeed == null) //we'll have to build it...
			{
				atomFeed = new AtomRoot();

				//However, if we made it this far, the not-modified check didn't work, and we may not have entries...
				if(entries == null)
				{
					entries = BuildEntries(category, maxDayCount, maxEntryCount);			
				}
			

				atomFeed.Lang = "en-us";
				atomFeed.Title = siteConfig.Title;
				atomFeed.Tagline = siteConfig.Subtitle;
				//atomFeed.Link = Utils.GetBaseUrl(siteConfig);
				atomFeed.Link = new AtomLink(Utils.GetBaseUrl(siteConfig));
				atomFeed.Author = new AtomParticipant();
				atomFeed.Author.Name = siteConfig.Copyright;
				atomFeed.Generator = new AtomGenerator();
				//atomFeed.Generator.Name = "newtelligence dasBlog " + GetType().Assembly.GetName().Version; 
				atomFeed.Generator.Url = "newtelligence dasBlog " + GetType().Assembly.GetName().Version;

				DateTime feedModified = DateTime.MinValue;

				foreach (Entry entry in entries)
				{
					if (entry.IsPublic == false)
					{
						continue;
					}

					string entryLink = Utils.GetPermaLinkUrl(siteConfig, entry);
					string entryGuid = Utils.GetPermaLinkUrl(siteConfig, entry.EntryId);
					
					AtomEntry atomEntry = new AtomEntry(entry.Title, new AtomLink(entryLink), entryGuid, entry.CreatedUtc, entry.ModifiedUtc);
					atomEntry.Created = entry.CreatedUtc;
					atomEntry.Summary = PreprocessItemContent(entry.EntryId, entry.Description);

					// only if we don't have a summary we emit the content
					if ( siteConfig.AlwaysIncludeContentInRSS || entry.Description == null || entry.Description.Length == 0 )
					{
						atomEntry.Summary = null; // remove empty summary tag

						try
						{
							AtomContent atomContent = new AtomContent();
							atomContent.Type = "text/html";
							atomContent.Mode = AtomContentMode.Xml;

							XmlDocument xmlDoc2 = new XmlDocument();
							xmlDoc2.LoadXml(ContentFormatter.FormatContentAsXHTML(PreprocessItemContent(entry.EntryId, entry.Content)));
							atomContent.anyElements = new XmlElement[]{xmlDoc2.DocumentElement}; 

							atomEntry.Content = atomContent;
						}
						catch
						{
							// absorb
						}
					}

					if (atomEntry.ModifiedUtc > feedModified)
						feedModified = atomEntry.ModifiedUtc;

					atomFeed.Entries.Add(atomEntry);
				}

				// set feed modified date to the most recent entry date
				atomFeed.ModifiedUtc = feedModified;
				HttpContext.Current.Cache.Insert(CacheKey,atomFeed,null,DateTime.Now.AddMinutes(5),System.Web.Caching.Cache.NoSlidingExpiration);
			}
            return atomFeed;
        }

    }
}
